﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace ES.Client.Expression.Field
{
    public class BaseParser
    {
        protected void BuildMemberName(MemberExpression expression, ref string field)
        {
            if (expression == null || expression.Expression == null)
            {
                return;
            }

            var parent = expression.Expression;
            if (parent.NodeType == ExpressionType.Parameter)
            {
                var memberName = this.GetMemberName(expression);
                field = string.IsNullOrWhiteSpace(field) ? memberName : memberName + "." + field;
            }

            if (parent.NodeType == ExpressionType.MemberAccess)
            {
                var memberName = this.GetMemberName(expression);
                field = string.IsNullOrWhiteSpace(field) ? memberName : memberName + "." + field;
                this.BuildMemberName(parent as MemberExpression, ref field);
            }
        }

        protected string GetMemberName(MemberExpression expression)
        {
            if (expression == null || expression.Member == null || string.IsNullOrWhiteSpace(expression.Member.Name))
            {
                return "";
            }

            var field = expression.Member.Name;

            var _properties = expression.Member.GetCustomAttributes(typeof(Nest.ElasticsearchPropertyAttributeBase), true).Cast<Nest.ElasticsearchPropertyAttributeBase>().ToList();
            if (_properties != null && _properties.Any())
            {
                var _property = _properties.FirstOrDefault();
                if (_property != null && !string.IsNullOrWhiteSpace(_property.Name))
                {
                    field = _property.Name;
                }
            }
            return field;
        }

        protected string Parse(MemberExpression expression)
        {
            var field = "";
            switch (expression.Expression.NodeType)
            {
                case ExpressionType.MemberAccess:
                    this.BuildMemberName(expression, ref field);
                    break;
                case ExpressionType.Parameter:
                    field = this.GetMemberName(expression);
                    break;
                default:
                    break;
            }

            return field;
        }
    }
}
